package com.ibeeking.found.open.b.rest.service.impl;

import com.ibeeking.found.common.entity.open.*;
import com.ibeeking.found.common.enums.OpenApiConfigEnum;
import com.ibeeking.found.common.enums.WxCpAppTypeEnum;
import com.ibeeking.found.common.enums.WxOpenAppTypeEnum;
import com.ibeeking.gmc.global.api.feign.GlobalOpenFeignClient;
import com.ibeeking.found.open.b.rest.service.IOpenService;
import com.ibeeking.found.open.b.rest.service.IWxCpEventService;
import com.ibeeking.found.open.b.rest.service.mq.WxCpDataTalkMsgEventHandler;
import com.ibeeking.found.open.b.rest.service.mq.WxCpFriendsMsgEventHandler;
import com.ibeeking.found.open.service.common.vo.OpenAuthViewVO;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.message.WxCpTpXmlMessage;
import me.chanjar.weixin.cp.bean.message.WxCpXmlMessage;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;


/**
 * @ClassName WxCpTpEventServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-18 12:21
 **/
@Service("wxCpEventServiceImpl")
public class WxCpEventServiceImpl implements IWxCpEventService {
    private static final Logger log = LoggerFactory.getLogger(WxCpEventServiceImpl.class);

    @Resource
    private IOpenService openServiceImpl;

    @Resource
    private GlobalOpenFeignClient globalOpenFeignClient;

    @Resource
    private WxCpFriendsMsgEventHandler wxCpFriendsMsgEventHandler;

    @Resource
    private WxCpDataTalkMsgEventHandler wxCpDataTalkMsgEventHandler;

    @Override
    public String checkWxCpSignature(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
        try {
            LogUtils.info("\nWxCpDkEventServiceImpl 接收到来自微信服务器的认证消息：signature = [{}], timestamp = [{}], nonce = [{}], echostr = [{}]",
                    signature, timestamp, nonce, echostr);

            WxCpService wxCpService = openServiceImpl.getDefaultWxCpService();
            if (wxCpService == null) throw new BusinessException("获取企微服务失败!");

            WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
            WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage);
            if (StringUtils.isNotBlank(echostr)) {
                if (!wxCpService.checkSignature(signature, timestamp, nonce, echostr)) {
                    return "非法请求";
                }
                String result =  cryptUtil.decrypt(echostr);
                LogUtils.info("\nWxCpEventServiceImpl decrypted echostr：[{}]",echostr);

                return result;
            }
            return "非法请求";
        }catch(Exception ex){
            LogUtils.error(ex.toString());
            return "非法请求";
        }

    }
    @Override
    public String authWxCpTicket(HttpServletRequest request, HttpServletResponse response, String signature, String timestamp, String nonce, String echostr) {
        try {

            WxCpService wxCpService = openServiceImpl.getDefaultWxCpService();
            if (wxCpService == null) throw new BusinessException("获取企微服务失败!");
            WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();

            WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage);
            String encryptedXml = IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8);

            String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, encryptedXml);
            if (inMessage == null) return "success";

            WxCpTpXmlMessage wxCpTpXmlMessage = WxCpTpXmlMessage.fromXml(inMessage);
            return "success";
        } catch (Exception ex) {
            return "success";
        }
    }

    @Override
    public Object msgWxCpEvent(HttpServletRequest request, HttpServletResponse response, String agentId, String signature, String timestamp, String nonce, String echostr) {
       try {
           WxCpService wxCpService = openServiceImpl.getDefaultWxCpService();
           if (wxCpService == null) {
               throw new BusinessException("获取企微服务失败!");
           }
           WxCpConfigStorage wxCpConfigStorage = wxCpService.getWxCpConfigStorage();
           WxCpCryptUtil cryptUtil = new WxCpCryptUtil(wxCpConfigStorage);
           String inMessage = cryptUtil.decryptXml(signature, timestamp, nonce, IOUtils.toString(request.getInputStream(), StandardCharsets.UTF_8));
           if(inMessage == null) return "success";
           LogUtils.info("msgCpEvent:消息解密后内容为：\n{} ", JsonUtils.toJsonStr(inMessage));

           WxCpXmlMessage wxCpXmlMessage = WxCpXmlMessage.fromXml(inMessage,agentId);

           if(WxCpConsts.EventType.CHANGE_EXTERNAL_TAG.equalsIgnoreCase(wxCpXmlMessage.getEvent())){
               if(WxCpConsts.ExternalTagChangeType.CREATE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
               || WxCpConsts.ExternalTagChangeType.UPDATE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
               || WxCpConsts.ExternalTagChangeType.DELETE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processFriendsTagsMsgEvent(wxCpXmlMessage);
               }
               if(WxCpConsts.ExternalTagChangeType.SHUFFLE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processFriendsShuffleTagsMsgEvent(wxCpXmlMessage);
               }
           }
           if(WxCpConsts.EventType.CHANGE_EXTERNAL_CONTACT.equalsIgnoreCase(wxCpXmlMessage.getEvent())){
               if(WxCpConsts.ExternalContactChangeType.ADD_EXTERNAL_CONTACT.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
               || WxCpConsts.ExternalContactChangeType.EDIT_EXTERNAL_CONTACT.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
               || WxCpConsts.ExternalContactChangeType.DEL_EXTERNAL_CONTACT.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processFriendsMsgEvent(wxCpXmlMessage);
               }
               if(WxCpConsts.ExternalContactChangeType.DEL_FOLLOW_USER.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processDeleteFriendsFollowMsgEvent(wxCpXmlMessage);
               }
               if(WxCpConsts.ExternalContactChangeType.ADD_HALF_EXTERNAL_CONTACT.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processFriendsHalfMsgEvent(wxCpXmlMessage);
               }
               if(WxCpConsts.ExternalContactChangeType.TRANSFER_FAIL.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processFriendsTransferFailfMsgEvent(wxCpXmlMessage);
               }
               if(WxCpConsts.MsgAuditChangeType.MSG_AUDIT_APPROVED.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpDataTalkMsgEventHandler.processmsgAuditApproveMsgEvent(wxCpXmlMessage);
               }
           }
           if(WxCpConsts.EventType.CHANGE_EXTERNAL_CHAT.equalsIgnoreCase(wxCpXmlMessage.getEvent())){
               if(WxCpConsts.ExternalChatChangeType.CREATE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
                       || WxCpConsts.ExternalChatChangeType.UPDATE.equalsIgnoreCase(wxCpXmlMessage.getChangeType())
                       || WxCpConsts.ExternalChatChangeType.DISMISS.equalsIgnoreCase(wxCpXmlMessage.getChangeType())){
                   wxCpFriendsMsgEventHandler.processGroupChatMsgEvent(wxCpXmlMessage);
               }
           }
           if(WxCpConsts.EventType.MSGAUDIT_NOTIFY.equalsIgnoreCase(wxCpXmlMessage.getEvent())){
               wxCpDataTalkMsgEventHandler.processNotifySyncMsgEvent(wxCpXmlMessage);
           }
           return "success";
       }catch(Exception ex){
           return "";
       }

    }
    @Override
    public OpenAuthViewVO queryOpenAuthViewByAllType(Long tenantId, Integer configType, Integer configSubType, Integer AppType){
        OpenAuthQuery query = new OpenAuthQuery();
        query.setTenantId(tenantId);
        query.setConfigType(configType);
        query.setConfigSubType(configSubType);
        query.setAppType(AppType);
        ResponseResult<OpenAuthDTO> responseResult = globalOpenFeignClient.queryOpenAuthOne(query);
        OpenAuthDTO openAuthDTO = responseResult.getData();
        if(openAuthDTO!=null){
            OpenAuthViewVO openAuthViewVO = BeanUtil.convertBean(openAuthDTO, OpenAuthViewVO.class);
            OpenAuthOfExtend openAuthOfExtend = openAuthDTO.getOpenAuthOfExtend();
            if(openAuthOfExtend!=null){
                if(configType== OpenApiConfigEnum.OPEN_CONFIG_TYPE_WECHAT_CP.getCode()){
                    if(configSubType == WxCpAppTypeEnum.WECHAT_CP_APP_TYPE_TP.getCode()){
                        OpenAuthOfWxCpTp openAuthOfWxCpTp =  openAuthOfExtend.getOpenAuthOfWxCpTp();
                        if(openAuthOfWxCpTp!=null) {
                            OpenAuthOfWxCpTpAuthCorpInfo authCorpInfo = openAuthOfWxCpTp.getAuthCorpInfo();
                            if(authCorpInfo!=null) {
                                openAuthViewVO.setName(authCorpInfo.getCorpName());
                                openAuthViewVO.setPrincipalName(authCorpInfo.getCorpFullName());
                                openAuthViewVO.setDescription(authCorpInfo.getCorpIndustry());
                                return openAuthViewVO;
                            }
                        }
                    }
                }
            }
        }
        return new OpenAuthViewVO();
    }

}
